package com.wuwei.elearning.setting.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wuwei.elearning.config.MinioConfig;
import com.wuwei.elearning.service.CacheService;
import com.wuwei.elearning.enumPackage.Constant;
import com.wuwei.elearning.exception.ElearningMysqlException;
import com.wuwei.elearning.question.domain.*;
import com.wuwei.elearning.question.mapper.*;
import com.wuwei.elearning.setting.domain.User;
import com.wuwei.elearning.setting.mapper.UserMapper;
import com.wuwei.elearning.setting.service.UserService;
import com.wuwei.elearning.utils.MD5Util;
import com.wuwei.elearning.utils.MinioUtil;
import com.wuwei.elearning.utils.result.Result;
import com.wuwei.elearning.utils.token.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {


    @Resource
    private UserMapper userMapper;

    @Resource
    private TestResultMapper testResultMapper;

    @Resource
    private TestAnswersMapper testAnswersMapper;
    @Autowired
    private CollectMapper collectMapper;
    @Autowired
    private FeedbackMapper feedbackMapper;
    @Autowired
    private LastRecordMapper lastRecordMapper;
    @Autowired
    private ListenRecordMapper listenRecordMapper;
    @Autowired
    private SelectRecordMapper selectRecordMapper;
    @Autowired
    private SelfTestMapper selfTestMapper;
    @Autowired
    private SelfTestAnswerMapper selfTestAnswerMapper;
    @Autowired
    private SelfTestRelationQuestionMapper selfTestRelationQuestionMapper;
    @Autowired
    private SelfTestResultMapper selfTestResultMapper;
    @Autowired
    private SubjectTestMapper subjectTestMapper;
    @Autowired
    private SubjectTestRelationQuestionMapper subjectTestRelationQuestionMapper;
    @Autowired
    private UserRecordMapper userRecordMapper;
    @Autowired
    private WrongRecordMapper wrongRecordMapper;


    @Override
    public Result<String> setPassword(User user, Long account, String newPassword) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(account!=null,User::getAccount,account);
        user.setAccount(account);
        user.setPassword(newPassword);
        int update = userMapper.update(user, updateWrapper);
        if (update!=1) {
            return Result.fail("密码修改失败！数据库修改失败");
        }
        return Result.ok("密码修改成功！");
    }

    /**
     * 删除用户信息的方法，除了删除user表，还要删除test_answers表和test_result表
     * @param id
     */
    @Override
    @Transactional
    public void deleteById(Long id) {
        User user = userMapper.selectById(id);
        userMapper.deleteById(id);

        LambdaQueryWrapper<TestResult> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TestResult::getAccount,user.getAccount());
        testResultMapper.delete(queryWrapper);

        LambdaQueryWrapper<TestAnswers> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(TestAnswers::getUserId,user.getAccount());
        testAnswersMapper.delete(queryWrapper1);
    }

    /**
     * 修改用户信息
     * 如果用户是学生
     * 修改用户绑定的课程
     * @param account
     * @param user
     */
    @Override
    @Transactional
    public void update(Long account, User user) {
        user.setEditBy(account);
        user.setUpdatedTime(LocalDateTime.now());
        userMapper.updateById(user);
        //如果用户原来是学生
        if (userMapper.selectById(user.getId()).getStatus()==2) {
            //删除用户原绑定的课程
            Long userAccount = user.getAccount();
            userRelationSubjectMapper.delete(new LambdaQueryWrapper<UserRelationSubject>()
                    .eq(UserRelationSubject::getAccount,userAccount));
            //新增绑定的课程
        }
    }

    @Override
    @Transactional
    public void regesiter(User user, Long createdBy, Long account) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getAccount,account);
        if (userMapper.selectOne(queryWrapper)!=null) {
            throw new ElearningMysqlException(30045,"注册失败！工号重复！");
        }
        //此时要将传进来的密码改为MD5加密的密文
        if (user.getStatus()==0) {
            throw new ElearningMysqlException(30045,"管理员帐号不允许注册！");
        }
        String md5 = MD5Util.getMD5(user.getPassword());
        LocalDateTime now = LocalDateTime.now();
        user.setCreatedTime(now);
        user.setCreatedBy(createdBy);
        user.setPassword(md5);
        userMapper.insert(user);
        String license = user.getLicense();
        List<Subject> subjects = subjectMapper.selectList(new LambdaQueryWrapper<Subject>().like(Subject::getName, "R3")
                .or().eq(Subject::getName,"综合阅读")
        );
        List<Long> subjectList = new ArrayList<>();
        //为指定类型的学员添加绑定的课程
        if ("TA".equals(license)) {
            subjectList = subjects.stream()
                    .filter(s -> !s.getName().equals("R3M6航空活塞发动机"))
                    .map(Subject::getId).collect(Collectors.toList());
        } else if ("PA".equals(license)) {
            subjectList = subjects.stream()
                    .filter(s -> !s.getName().equals("R3M5航空涡轮发动机"))
                    .map(Subject::getId)
                    .collect(Collectors.toList());;
        } else if ("补差".equals(license)) {
            String subject = user.getSubject();
            JSONArray jsonArray = JSON.parseArray(subject);
            for (Object object : jsonArray) {
                Long subjectId = Long.parseLong(object.toString());
                subjectList.add(subjectId);
            }
        }
        List<Long> subjectIds = new ArrayList<>();
        subjectList.forEach(subjectId->{
            List<Long> sonsById = subjectMapper.getSonsById(subjectId);
            subjectIds.addAll(sonsById);
        });
        if (!subjectIds.isEmpty()) {
            userRelationSubjectMapper.myBatchInsertByAccount(user.getAccount(),subjectIds);
        }
    }

    /**
     * 根据account
     * 删除user表
     * collect
     * feedback
     * last_record
     * listen_record
     * select_record
     * self_test
     * self_test_answer
     * self_test_relation_question
     * self_test_result
     * subject_test
     * subject_test_relation_question
     * test_answers
     * test_result
     * user_record
     * user_relation_subject
     * wrong_record
     * @param id user表的id
     */
    @Override
    @Transactional
    public void myDelete(Long id) {
        User user = userMapper.selectById(id);
        Long account = user.getAccount();
        // 删除collect表
        collectMapper.delete(new LambdaQueryWrapper<Collect>().eq(Collect::getUserAccount,account));
        //删除feedback表
        feedbackMapper.delete(new LambdaQueryWrapper<Feedback>().eq(Feedback::getCreatedBy,account));
        //删除last_record表
        lastRecordMapper.delete(new LambdaQueryWrapper<LastRecord>().eq(LastRecord::getUserAccount,account));
        //删除listen_record表
        listenRecordMapper.delete(new LambdaQueryWrapper<ListenRecord>().eq(ListenRecord::getAccount,account));
        //删除select_record表
        selectRecordMapper.delete(new LambdaQueryWrapper<SelectRecord>().eq(SelectRecord::getUserAccount,account));
        //删除self_test表
        LambdaQueryWrapper<SelfTest> wrapper = new LambdaQueryWrapper<SelfTest>().eq(SelfTest::getCreateBy, account);
        List<Long> selfTestIds = selfTestMapper.selectList(wrapper).stream().map(SelfTest::getId).collect(Collectors.toList());
        selfTestMapper.delete(wrapper);
        //删除self_test_answer表
        selfTestAnswerMapper.delete(new LambdaQueryWrapper<SelfTestAnswer>().eq(SelfTestAnswer::getUserAccount,account));
        if (!selfTestIds.isEmpty()) {
            //删除self_test_relation_question表
            selfTestRelationQuestionMapper.delete(new LambdaQueryWrapper<SelfTestRelationQuestion>().in(SelfTestRelationQuestion::getSelfTestId,selfTestIds));
        }
        //删除self_test_result表
        selfTestResultMapper.delete(new LambdaQueryWrapper<SelfTestResult>().eq(SelfTestResult::getAccount,account));
        //删除subject_test表
        LambdaQueryWrapper<SubjectTest> wrapper1 = new LambdaQueryWrapper<SubjectTest>().eq(SubjectTest::getAccount, account);
        List<Long> subjectTestIds = subjectTestMapper.selectList(wrapper1).stream().map(SubjectTest::getId).collect(Collectors.toList());
        subjectTestMapper.delete(wrapper1);
        if (!subjectTestIds.isEmpty()) {
            //删除subject_test_relation_question表
            subjectTestRelationQuestionMapper.delete(new LambdaQueryWrapper<SubjectTestRelationQuestion>().in(SubjectTestRelationQuestion::getSubjectTestId,subjectTestIds));
        }
        //删除test_answers表
        testAnswersMapper.delete(new LambdaQueryWrapper<TestAnswers>().eq(TestAnswers::getUserId,account));
        //删除test_result表
        testResultMapper.delete(new LambdaQueryWrapper<TestResult>().eq(TestResult::getAccount,account));
        //删除user_record表
        userRecordMapper.delete(new LambdaQueryWrapper<UserRecord>().eq(UserRecord::getUserAccount,account));
        //删除user_relation_subject表
        userRelationSubjectMapper.delete(new LambdaQueryWrapper<UserRelationSubject>().eq(UserRelationSubject::getAccount,account));
        //删除wrong_record表
        wrongRecordMapper.delete(new LambdaQueryWrapper<WrongRecord>().eq(WrongRecord::getUserAccount,account));
        //删除user表
        userMapper.deleteById(id);
    }

    @Override
    @Transactional
    public String uploadAvator(MultipartFile file, String token) {
        if (file.getSize() != 0) {
            String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
            String upperCase = suffix.toUpperCase();
            String jpg = "jpg".toUpperCase();
            String png = "png".toUpperCase();
            String gif = "gif".toUpperCase();
            String jpeg = "jpeg".toUpperCase();
            if (!jpg.equals(upperCase) && !png.equals(upperCase) && !gif.equals(upperCase)&&!jpeg.equals(upperCase)) {
                throw new ElearningMysqlException(30055,"请选择jpg或png或gif格式的图片！");
            }

            if (file.getSize() != 0) {
                String previewUrl = null;
                try {
                    // 先更新数据库
                    String upload = minioUtil.upload(file);
                    Long account = TokenUtil.getAccountFromToken(token);
                    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(User::getAccount, account);
                    User user = userMapper.selectOne(wrapper);
                    user.setAvatar(upload);
                    user.setUpdatedTime(LocalDateTime.now());
                    user.setEditBy(account);
                    userMapper.updateById(user);
                    // 然后更新缓存
                    previewUrl = minioUtil.getPreviewUrl(upload);
                    previewUrl = minioConfig.getEndpoint() + previewUrl;
                    String redisKey = Constant.MINIO_AVATAR + upload;
                    cacheService.setEx(redisKey, previewUrl, 6, TimeUnit.DAYS);
                } catch (Exception e) {
                    // 如果缓存更新失败，执行补偿逻辑
                    // 这里可以记录日志或触发异步补偿操作
                    throw new RuntimeException(e);
                }
                return previewUrl;
            }
            throw new ElearningMysqlException(30055,"上传失败！");
        } else {
            throw new ElearningMysqlException(30055,"您没有上传任何文件");
        }
    }

    @Resource
    private MinioConfig minioConfig;

    @Resource
    private MinioUtil minioUtil;

    @Resource
    private CacheService cacheService;

    @Override
    public User getUserInfo(String token) {
        // 处理业务逻辑
        Long account = TokenUtil.getAccountFromToken(token);
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getAccount, account);
        User user = userMapper.selectOne(queryWrapper);

        // 从Redis获取缓存的预览URL或生成新的
        String avatar = user.getAvatar();
        // 构建Redis键
        String redisKey = Constant.MINIO_AVATAR + avatar;

        // 尝试从Redis获取
        String userAvatar = cacheService.getAvatar(avatar, redisKey);
        user.setAvatar(userAvatar);
        return user;
    }



    @Resource
    private SubjectMapper subjectMapper;

    @Resource
    private UserRelationSubjectMapper userRelationSubjectMapper;

}
